using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;

namespace Budgetor
{
    public partial class PieChartControl : UserControl
    {
        PieChartSliceCollection slices = new PieChartSliceCollection();

        public PieChartControl()
        {
            InitializeComponent();
            // Enable double buffering
            this.SetStyle(
             ControlStyles.AllPaintingInWmPaint |
             ControlStyles.UserPaint |
             ControlStyles.DoubleBuffer, true);
        }

        public void AddData(string description, float amount)
        {
            //if (data.ContainsKey(description))
            //    data[description] += amount;
            //else
            //    data.Add(description, amount);

            slices.Add(description, amount);

            //slices.Clear();

            //float total = 0;
            //foreach (float amount in data.Values)
            //{
            //    total += amount;
            //}

            //float startAngle = 0, sweepAngle;

            //foreach (float amount in data.Values)
            //{
            //    sweepAngle = amount / total * 360;
            //    e.Graphics.FillPie(new SolidBrush(GetRandomColor()), rectangle, startAngle, sweepAngle);
            //    startAngle += sweepAngle;
            //}
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            Graphics graphics = e.Graphics;

            graphics.SmoothingMode = SmoothingMode.AntiAlias;
            Font font = new Font("Tahoma", 8);

            float maxTextWidth = 0;
            float maxTextHeight = 0;
            foreach (string description in slices.Keys)
            {
                Size textSize = TextRenderer.MeasureText(description, font);

                maxTextWidth = Math.Max(maxTextWidth, textSize.Width);
                maxTextHeight = Math.Max(maxTextHeight, textSize.Height);
            }

            Rectangle pieRectangle = new Rectangle(20, 20, this.Width - 20 - (int)maxTextWidth - 70, this.Height - 40);

            // Make this rectangle a square
            if (pieRectangle.Width > pieRectangle.Height)
                pieRectangle.Inflate((pieRectangle.Height - pieRectangle.Width) / 2, 0);
            else if (pieRectangle.Height > pieRectangle.Width)
                pieRectangle.Inflate(0, (pieRectangle.Width - pieRectangle.Height) / 2);

            float startAngle = 0, sweepAngle;
            PointF textPosition = new PointF(this.Width - 20 - maxTextWidth, 20);

            foreach (KeyValuePair<string, KeyValuePair<Color, float>> slice in slices)
            {
                Brush brush = new SolidBrush(slice.Value.Key);

                sweepAngle = slice.Value.Value / slices.TotalAmount * 360;
                e.Graphics.FillPie(brush, pieRectangle, startAngle, sweepAngle);
                startAngle += sweepAngle;

                graphics.FillRectangle(brush, textPosition.X - 30, textPosition.Y, 20, 10);
                graphics.DrawRectangle(Pens.Black, textPosition.X - 30, textPosition.Y, 20, 10);
                graphics.DrawString(slice.Key, font, Brushes.Black, textPosition);
                textPosition.Y += maxTextHeight;
            }

            startAngle = sweepAngle = 0;
            foreach (KeyValuePair<Color, float> amount in slices.Values)
            {
                sweepAngle = amount.Value / slices.TotalAmount * 360;
                e.Graphics.DrawPie(Pens.Black, pieRectangle, startAngle, sweepAngle);
                startAngle += sweepAngle;
            }

            base.OnPaint(e);
        }

        protected override void OnResize(EventArgs e)
        {
            this.Invalidate();
            base.OnResize(e);
        }

        internal class PieChartSlice
        {
            private string description;
            public string Description
            {
                get { return description; }
                set { description = value; }
            }

            private float val;
            public float Value
            {
                get { return val; }
                set { val = value; }
            }

            private Color color;
            public Color Color
            {
                get { return color; }
                set { color = value; }
            }

            public PieChartSlice(string description, float value, Color color)
            {
                this.description = description;
                this.val = value;
                this.color = color;
            }
        }

        internal class PieChartSliceCollection : Dictionary<string, KeyValuePair<Color, float>>
        {
            //public bool ContainsDescription(string description)
            //{
            //    foreach (PieChartSlice slice in this)
            //    {
            //        if (slice.Description == description)
            //            return true;
            //    }

            //    return false;
            //}

            private static Color[] colorList = new Color[] { 
                Color.Red, Color.Blue, Color.Green, Color.Cyan, Color.Magenta,
                Color.Yellow, Color.Gray, Color.Maroon, Color.Brown, Color.Tomato,
                Color.Sienna, Color.Orange, Color.Olive, Color.Lime, Color.SeaGreen,
                Color.DarkSlateGray, Color.RoyalBlue, Color.Indigo, Color.Violet, Color.Purple};

            public void Add(string description, float value)
            {
                if (this.ContainsKey(description))
                {
                    this[description] = new KeyValuePair<Color, float>(
                        this[description].Key, this[description].Value + value);
                }
                else
                {
                    Color color;
                    bool uniqueColorFound;

                    do
                    {
                        if (this.Count < colorList.GetLength(0))
                            color = colorList[this.Count];
                        else
                            color = GetRandomColor();

                        uniqueColorFound = true;
                        foreach (KeyValuePair<Color, float> slice in this.Values)
                        {
                            if (slice.Key == color)
                                uniqueColorFound = false;
                        }
                    } while (uniqueColorFound != true);

                    this.Add(description, new KeyValuePair<Color, float>(color, value));
                }

                total += value;
            }

            private float total = 0;
            public float TotalAmount
            {
                get { return total; }
            }


            static Random random = new Random();

            public static Color GetRandomColor()
            {
                KnownColor[] colors = (KnownColor[])Enum.GetValues(typeof(KnownColor));

                return Color.FromKnownColor(colors[random.Next(colors.Length)]);
            }
        }
   }

}
